package ai.people.netmon.warning.service.impl;

import ai.people.netmon.framework.domain.common.NameValueEntity;
import ai.people.netmon.framework.domain.common.TypeValueEntity;
import ai.people.netmon.framework.domain.warning.dto.AnalysisRequestContext;
import ai.people.netmon.framework.domain.warning.vo.MessageContentVO;
import ai.people.netmon.framework.domain.warning.vo.TrendAnalysisRespVO;
import ai.people.netmon.framework.exception.enums.CommonEnum;
import ai.people.netmon.framework.model.response.Result;
import ai.people.netmon.framework.utils.AssertUtils;
import ai.people.netmon.framework.utils.ResultUtil;
import ai.people.netmon.utils.localdateUtil.DateTimeFormatterUtil;
import ai.people.netmon.warning.service.WarningAnalysisTaskLink;
import ai.people.netmon.warning.service.WarningAnalysisTaskOrder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.huaban.analysis.jieba.keyword.Keyword;
import com.huaban.analysis.jieba.keyword.TFIDFAnalyzer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * impl预警分析计算任务
 *
 * @author LiGuanNan
 * @date 2022/8/15 10:50
 */
@Slf4j
@Service
public class WarningAnalysisComputeTaskImpl extends WarningAnalysisTaskLink implements WarningAnalysisTaskOrder {

    @Autowired
    private DoAnalysisComputeTaskFactory doAnalysisComputeTaskFactory;


    /**
     * 得到顺序
     *
     * @return int
     */
    @Override
    public int getOrder() {
        return 30;
    }

    /**
     * 做任务
     *
     * @param paramContext 参数上下文
     * @return {@link T}
     */
    @Override
    public <T> Result<List<T>> doTask(AnalysisRequestContext<T> paramContext) {
        return ResultUtil.success(doAnalysisComputeTaskFactory.findTask(paramContext.getModelKey()).doAnalysisCompute(paramContext));
    }

    /**
     * 执行消息搜索任务
     *
     * @author ligua
     * @date 2022/08/15
     */
    interface DoAnalysisComputeTask<T> {

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link T}>
         */
        List<T> doAnalysisCompute(AnalysisRequestContext<T> paramContext);
    }

    /**
     * 情感分析计算
     *
     * @author ligua
     * @date 2022/08/15
     */
    @Component("warningAnalysis_compute_emotion_value")
    static class EmotionAnalysisCompute implements DoAnalysisComputeTask<TypeValueEntity<String, Long>>{

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link TypeValueEntity}<{@link String}, {@link Long}>>
         */
        @Override
        public List<TypeValueEntity<String, Long>> doAnalysisCompute(AnalysisRequestContext<TypeValueEntity<String, Long>> paramContext) {
            List<TypeValueEntity<String, Long>> list = Lists.newArrayList();
            List<MessageContentVO> vos = paramContext.getMessageContentList();
            if(!CollectionUtils.isEmpty(vos)){
                Map<String, Long> map = vos.stream().filter(o-> !StringUtils.isEmpty(o.getEmotion())).collect(Collectors.groupingBy(MessageContentVO::getEmotion, Collectors.counting()));
                map.keySet().forEach(key->{
                    list.add(TypeValueEntity.<String,Long>builder().type(key).value(map.get(key)).build());
                });
            }
            return list;
        }
    }

    @Component("warningAnalysis_compute_source_value")
    static class SourceAnalysisCompute implements DoAnalysisComputeTask<TypeValueEntity<String, Long>>{

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link TypeValueEntity}<{@link String}, {@link Long}>>
         */
        @Override
        public List<TypeValueEntity<String, Long>> doAnalysisCompute(AnalysisRequestContext<TypeValueEntity<String, Long>> paramContext) {
            List<TypeValueEntity<String, Long>> list = Lists.newArrayList();
            List<MessageContentVO> vos = paramContext.getMessageContentList();
            if(!CollectionUtils.isEmpty(vos)){
                Map<String, Long> map = vos.stream().filter(o-> !StringUtils.isEmpty(o.getPlatform())).collect(Collectors.groupingBy(MessageContentVO::getPlatform, Collectors.counting()));
                map.keySet().forEach(key->{
                    list.add(TypeValueEntity.<String,Long>builder().type(key).value(map.get(key)).build());
                });
            }
            return list;
        }
    }

    /**
     * 趋势分析计算
     *
     * @author ligua
     * @date 2022/08/15
     */
    @Component("warningAnalysis_compute_trend_value")
    static class TrendAnalysisCompute implements DoAnalysisComputeTask<TrendAnalysisRespVO>{

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link TrendAnalysisRespVO}>
         */
        @Override
        public List<TrendAnalysisRespVO> doAnalysisCompute(AnalysisRequestContext<TrendAnalysisRespVO> paramContext) {
            List<TrendAnalysisRespVO> resultList = Lists.newArrayList();
            List<MessageContentVO> vos = paramContext.getMessageContentList();
            if(!CollectionUtils.isEmpty(vos)){
                Map<String, List<MessageContentVO>> map = vos.stream().filter(o-> !StringUtils.isEmpty(o.getEmotion())).collect(Collectors.groupingBy(MessageContentVO::getEmotion));
                map.keySet().forEach(key->{
                    Map<String, Long> collect = map.get(key).stream().filter(o-> !StringUtils.isEmpty(o.getEmotion())).collect(Collectors.groupingBy(o -> DateTimeFormatter.ofPattern("yyyy-MM-dd").format(o.getTime()), Collectors.counting()));
                    collect.keySet().forEach(year->{
                        resultList.add(TrendAnalysisRespVO.builder().category(key).year(year).value(collect.get(year)).build());
                    });
                });
            }
            return paddingList(resultList);
        }
    }

    /**
     * 标签分析计算
     *
     * @author ligua
     * @date 2022/08/15
     */
    @Component("warningAnalysis_compute_tag_value")
    static class TagAnalysisCompute implements DoAnalysisComputeTask<TrendAnalysisRespVO>{

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link TrendAnalysisRespVO}>
         */
        @Override
        public List<TrendAnalysisRespVO> doAnalysisCompute(AnalysisRequestContext<TrendAnalysisRespVO> paramContext) {
            List<TrendAnalysisRespVO> resultList = Lists.newArrayList();
            List<MessageContentVO> vos = paramContext.getMessageContentList();
            if(!CollectionUtils.isEmpty(vos)){
                Map<String, List<MessageContentVO>> map = vos.stream()
                        .filter(o-> Objects.nonNull(o.getTime()) && !StringUtils.isEmpty(o.getLabel()))
                        .collect(Collectors.groupingBy(o -> DateTimeFormatter.ofPattern("yyyy-MM-dd").format(o.getTime())));
                map.keySet().forEach(year->{
                    List<String> tags = Lists.newArrayList();
                    map.get(year).forEach(o->tags.addAll(Arrays.asList(o.getLabel().split(","))));
                    Map<String, Long> collect = tags.stream().collect(Collectors.groupingBy(String::trim, Collectors.counting()));
                    collect.keySet().forEach(key->{
                        resultList.add(TrendAnalysisRespVO.builder().category(key).year(year).value(collect.get(key)).build());
                    });
                });
            }
            return paddingList(resultList);
        }
    }

    /**
     * 关键词分析计算
     *
     * @author ligua
     * @date 2022/08/15
     */
    @Component("warningAnalysis_compute_keyword_value")
    static class KeywordAnalysisCompute implements DoAnalysisComputeTask<NameValueEntity<String, Double>>{

        /**
         * 进行分析计算
         *
         * @param paramContext 参数上下文
         * @return {@link List}<{@link NameValueEntity}<{@link String}, {@link Double}>>
         */
        @Override
        public List<NameValueEntity<String, Double>> doAnalysisCompute(AnalysisRequestContext<NameValueEntity<String, Double>> paramContext) {
            List<NameValueEntity<String, Double>> list = Lists.newArrayList();
            List<MessageContentVO> vos = paramContext.getMessageContentList();
            Map<String, Double> keywordMap = Maps.newHashMap();
            if(!CollectionUtils.isEmpty(vos)){
                vos.stream().filter(o->!StringUtils.isEmpty(o.getContent())).map(MessageContentVO::getContent).forEach(o->{
                    TFIDFAnalyzer tfidfAnalyzer = new TFIDFAnalyzer();
                    List<Keyword> keywords = tfidfAnalyzer.analyze(o, 30);
                    keywords.forEach(keyword -> {
                        Double aDouble = keywordMap.get(keyword.getName());
                        if(aDouble != null){
                            keywordMap.put(keyword.getName(),aDouble + keyword.getTfidfvalue());
                        }else {
                            keywordMap.put(keyword.getName(),keyword.getTfidfvalue());
                        }
                    });
                });
            }
            if(!CollectionUtils.isEmpty(keywordMap)){
                list = keywordMap.entrySet().stream()
                        .sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
                        .limit(30)
                        .map(o->NameValueEntity.<String, Double>builder().name(o.getKey()).value(o.getValue()).build())
                        .collect(Collectors.toList());
            }
            return list;
        }
    }

    /**
     * 查找真正执行的任务
     */
    @Component("doAnalysisComputeTaskFactory")
    static class DoAnalysisComputeTaskFactory {

        @Autowired
        private Map<String, DoAnalysisComputeTask> doAnalysisComputeTaskMap;

        /**
         * 找到任务
         *
         * @param modelKey 模型关键词
         * @return {@link DoAnalysisComputeTask}
         */
        public DoAnalysisComputeTask findTask(String modelKey) {
            DoAnalysisComputeTask doAnalysisComputeTask = doAnalysisComputeTaskMap.get(String.format("warningAnalysis_compute_%s", modelKey));
            AssertUtils.isNotNull(doAnalysisComputeTask, CommonEnum.OPT_NOT_SUPPORT);
            return doAnalysisComputeTask;
        }
    }

    /**
     * 填充列表
     *
     * @param resultList 结果列表
     * @return {@link List}<{@link TrendAnalysisRespVO}>
     */
    private static List<TrendAnalysisRespVO> paddingList(List<TrendAnalysisRespVO> resultList) {
        List<TrendAnalysisRespVO> vos = Lists.newArrayList();
        if(!CollectionUtils.isEmpty(resultList)){
            Map<String, List<TrendAnalysisRespVO>> categoryMap = resultList.stream().collect(Collectors.groupingBy(TrendAnalysisRespVO::getCategory));
            categoryMap.keySet().forEach(category->{
                List<TrendAnalysisRespVO> list = categoryMap.get(category);
                list.sort(Comparator.comparing(TrendAnalysisRespVO::getYear));
                for(int i = 0; i< list.size(); i++){
                    TrendAnalysisRespVO currentVo = list.get(i);
                    LocalDate currentDate = DateTimeFormatterUtil.stringDateFormatterToLocalDate(currentVo.getYear());
                    vos.add(currentVo);
                    if(i != 0){
                        TrendAnalysisRespVO preVo = list.get(i - 1);
                        if(isIntervalGreaterThanOneDay(preVo, currentVo)){
                            vos.add(TrendAnalysisRespVO.builder().category(category).year(DateTimeFormatterUtil.localDateFormatterToStringDate(currentDate.plusDays(-1))).value(0L).build());
                        }
                    }
                    if(i != list.size() - 1){
                        TrendAnalysisRespVO nextVo = list.get(i + 1);
                        if(isIntervalGreaterThanOneDay(currentVo, nextVo)){
                            vos.add(TrendAnalysisRespVO.builder().category(category).year(DateTimeFormatterUtil.localDateFormatterToStringDate(currentDate.plusDays(1))).value(0L).build());
                        }
                    }
                }
            });
            vos.sort(Comparator.comparing(TrendAnalysisRespVO::getYear));
        }
        return vos;
    }

    /**
     * 是否间隔大于一天
     *
     * @param currentVo 目前签证官
     * @param nextVo    下一个签证官
     * @return boolean
     */
    private static boolean isIntervalGreaterThanOneDay(TrendAnalysisRespVO currentVo, TrendAnalysisRespVO nextVo) {
        return DateTimeFormatterUtil.stringDateFormatterToLocalDate(currentVo.getYear()).plusDays(1).compareTo(DateTimeFormatterUtil.stringDateFormatterToLocalDate(nextVo.getYear())) < 0;
    }

}
